package io.kiki.sba.registry.server.metadata.resource;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
import io.kiki.sba.registry.common.model.Response;
import io.kiki.sba.registry.metrics.ReporterUtils;
import io.kiki.sba.registry.server.metadata.MetadataLeaderService;
import io.kiki.sba.registry.server.metadata.bootstrap.MetaServerBootstrap;
import io.kiki.sba.registry.server.metadata.metadataServer.CurrentNodeClusterMetadataServer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;

/**
 * @author shangyu.wh
 * @version $Id: PushSwitchResource.java, v 0.1 2018-10-29 16:51 shangyu.wh Exp $
 */
@Path("health")
public class HealthResource {

    @Autowired
    private MetaServerBootstrap metaServerBootstrap;

    @Autowired
    private MetadataLeaderService metadataLeaderService;

    @Autowired
    private CurrentNodeClusterMetadataServer currentDcMetaServer;

    @PostConstruct
    public void init() {
        MetricRegistry metrics = new MetricRegistry();
        metrics.register("healthCheck", (Gauge<Response>) () -> getHealthCheckResult());
        ReporterUtils.startSlf4jReporter(60, metrics);
    }

    @GET
    @Path("check")
    @Produces(MediaType.APPLICATION_JSON)
    public javax.ws.rs.core.Response checkHealth() {
        ResponseBuilder builder = javax.ws.rs.core.Response.status(javax.ws.rs.core.Response.Status.OK);
        Response response = getHealthCheckResult();
        builder.entity(response);
        if (!response.isSuccess()) {
            builder.status(Status.INTERNAL_SERVER_ERROR);
        }
        return builder.build();
    }

    private Response getHealthCheckResult() {
        Response response;

        StringBuilder sb = new StringBuilder("MetaServerBoot ");

        boolean start = metaServerBootstrap.isRpcServerForSessionStarted();
        boolean ret = start;
        sb.append("sessionRegisterServer:").append(start);

        start = metaServerBootstrap.isRpcServerForDataStarted();
        ret = ret && start;
        sb.append(", dataRegisterServerStart:").append(start);

        start = metaServerBootstrap.isRpcServerForMetaStarted();
        ret = ret && start;
        sb.append(", otherMetaRegisterServerStart:").append(start);

        start = metaServerBootstrap.isHttpServerStarted();
        ret = ret && start;
        sb.append(", httpServerStart:").append(start);

        start = metaServerBootstrap.isRpcServerForRemoteMetaStarted();
        ret = ret && start;
        sb.append(", remoteMetaRegisterServerStart:").append(start);

        boolean leaderNotEmpty = StringUtils.isNotBlank(metadataLeaderService.getLeader());
        ret = ret && leaderNotEmpty;

        sb.append(", role:").append(metadataLeaderService.amILeader() ? "leader" : "follower");
        sb.append(", warmuped:").append(metadataLeaderService.isWarmuped());
        sb.append(", leader:").append(metadataLeaderService.getLeader());
        sb.append(", meta-servers:").append(currentDcMetaServer.getList());

        if (ret) {
            response = Response.buildSuccessResponse(sb.toString());
        } else {
            response = Response.buildFailedResponse(sb.toString());
        }
        return response;
    }


    protected HealthResource setMetaServerBootstrap(MetaServerBootstrap metaServerBootstrap) {
        this.metaServerBootstrap = metaServerBootstrap;
        return this;
    }


    protected HealthResource setMetaLeaderService(MetadataLeaderService metadataLeaderService) {
        this.metadataLeaderService = metadataLeaderService;
        return this;
    }


    protected HealthResource setCurrentDcMetaServer(CurrentNodeClusterMetadataServer currentDcMetaServer) {
        this.currentDcMetaServer = currentDcMetaServer;
        return this;
    }
}
